/**
 * Created by jazhang on 12/13/13.
 */

axisDistribution = [
[3,5,1,7,4,3,3,2,6,5],
[2,1,2,3,4,5,6,7,8,9],
[3,1,2,7,4,5,3,7,4,0],
[1,3,2,9,1,0,1,4,2,3],
[0,2,3,6,4,3,2,1,0,1],
[1,2,0,8,2,3,5,4,3,1],
[4,0,1,3,2,6,4,3,2,1],
[0,1,2,5,4,7,3,1,2,1]
];
var RadarChart = {
    rotateAngle: 0, // radians
    chartId: null,
    data: null,
    options: null,
    drawBarFunction: null,
    drawLegendFunction: null,

    draw: function () {
        var cfg = {
            radius: 5,
            w: 600,
            h: 600,
            factor: 1,
            factorLegend: 0.85,
            levels: 6,
            maxValue: 0,
            radians: 2 * Math.PI,
            opacityArea: 0.5,
            ToRight: 5,
            TranslateX: 80,
            TranslateY: 30,
            ExtraWidthX: 100,
            ExtraWidthY: 100,
            color: d3.scale.category10()
        };

        var id = this.chartId,
            d = this.data,
            options = this.options,
            drawBar = this.drawBarFunction,
            rotateAngle = this.rotateAngle; // Math.PI / 180 * 90;
        var TWO_PI = 2 * Math.PI;


        if ('undefined' !== typeof options) {
            for (var i in options) {
                if ('undefined' !== typeof options[i]) {
                    cfg[i] = options[i];
                }
            }
        }
        cfg.maxValue = Math.max(cfg.maxValue, d3.max(d, function (i) {
            return d3.max(i.map(function (o) {
                return o.value;
            }))
        }));
        var allAxis = (d[0].map(function (i, j) {
            return i.axis
        }));
        var total = allAxis.length;
        var radius = cfg.factor * Math.min(cfg.w / 2, cfg.h / 2);
        var Format = d3.format('%');
        d3.select(id).select("svg").remove();

        var prevMousePos,
            curMousePos,
            centerPos = [430, 330]; // X, Y coordinates
        
        function handleMousedown() {
            var evt = d3.event;
            
            prevMousePos = [evt.pageX, evt.pageY];
            // console.log("Dn x: " + evt.pageX + ", y: " + evt.pageY);
            d3.select(window)
                // .on("mousemove", handleMousemove)
                .on("mouseup", handleMouseup);
            // d3.event.preventDefault();
        }
        
        function handleMousemove() {
            var evt = d3.event;
            
            curMousePos = [evt.pageX, evt.pageY];
            // console.log("Mv x: " + evt.pageX + ", y: " + evt.pageY);
        }
        
        function handleMouseup() {
            var evt = d3.event,
                prevAngle,
                curAngle,
                rotateAngle;
            
            curMousePos = [evt.pageX, evt.pageY];
            // console.log("Up x: " + evt.pageX + ", y: " + evt.pageY);
            d3.select(window)
                // .on("mousemove", null)
                .on("mouseup", null);

            prevAngle = Math.atan2((prevMousePos[1] - centerPos[1]), (prevMousePos[0] - centerPos[0]));
            curAngle = Math.atan2((curMousePos[1] - centerPos[1]), (curMousePos[0] - centerPos[0]));
            rotateAngle = curAngle - prevAngle;
            // console.log("PrevAngle=" + prevAngle * 180 / Math.PI + ", curAngle=" + curAngle * 180 / Math.PI + ", rotateAngle=" + rotateAngle * 180 / Math.PI);
            if(rotateAngle === 0) {
                return;
            }
            
            rotateAngle = RadarChart.rotateAngle - rotateAngle; // Inverse rotateAngle before adding it to RadarChart's current rotateAngle 
            if (rotateAngle > TWO_PI) {
                rotateAngle -= TWO_PI;
            }
            else if (rotateAngle < - TWO_PI) {
                rotateAngle += TWO_PI;
            }
            // update rotateAngle
            RadarChart.rotateAngle = rotateAngle;
            RadarChart.draw();
            RadarChart.drawLegendFunction(RadarChart.data);
        }
        
        var g = d3.select(id)
            .append("svg")
            .attr("width", cfg.w + cfg.ExtraWidthX)
            .attr("height", cfg.h + cfg.ExtraWidthY)
            .on("mousedown", handleMousedown)
            .append("g")
            .attr("transform", "translate(" + cfg.TranslateX + "," + cfg.TranslateY + ")");


        
        
        var tooltip;

        if(total <= 0) {
            g.append("svg:text")
                .text("No data to view. Please select at least one column.")
                .attr("transform", "translate(200, 100)")
                .style("font-family", "sans-serif")
                .style("font-size", "18px");
            return;
        }

        //Circular segments
        var radDivide = cfg.radians/total;
        for (var j = 1; j < cfg.levels; j++) {
            var levelFactor = cfg.factor * radius * (j/ cfg.levels);
            g.selectAll(".levels")
                .data(allAxis)
                .enter()
                .append("svg:line")
                .attr("x1", function (d, i) {
                    return levelFactor * ( - cfg.factor * Math.sin(rotateAngle + i * radDivide));
                })
                .attr("y1", function (d, i) {
                    return levelFactor * ( -cfg.factor * Math.cos(rotateAngle + i * radDivide));
                })
                .attr("x2", function (d, i) {
                    return levelFactor * (- cfg.factor * Math.sin(rotateAngle + (i + 1) * radDivide));
                })
                .attr("y2", function (d, i) {
                    return levelFactor * (-cfg.factor * Math.cos(rotateAngle + (i + 1) * radDivide));
                })
                .attr("class", "line")
                .style("stroke", "grey")
                .style("stroke-opacity", "0.75")
                .style("stroke-width", "0.3px")
                .attr("transform", "translate(" + (cfg.w / 2 ) + ", " + (cfg.h / 2 ) + ")");
        }

        //Text indicating at what % each level is
        for (var j = 0; j < cfg.levels; j++) {
            var levelFactor = cfg.factor * radius * ((j + 1) / cfg.levels);
            g.selectAll(".levels")
                .data([1]) //dummy data
                .enter()
                .append("svg:text")
                .attr("x", function (d) {
                    return levelFactor * (1 - cfg.factor * Math.sin(rotateAngle + 0));
                })
                .attr("y", function (d) {
                    return levelFactor * (1 - cfg.factor * Math.cos(rotateAngle + 0));
                })
                .attr("class", "legend")
                .style("font-family", "sans-serif")
                .style("font-size", "10px")
                .attr("transform", "translate(" + (cfg.w / 2 - levelFactor + cfg.ToRight) + ", " + (cfg.h / 2 - levelFactor) + ")")
                .attr("fill", "#737373")
                .text(Format((j + 1) * cfg.maxValue / cfg.levels));
        }

        series = 0;

        var axis = g.selectAll(".axis")
            .data(allAxis)
            .enter()
            .append("g")
            .attr("class", "axis");

        axis.append("line")
            .attr("x1", cfg.w / 2)
            .attr("y1", cfg.h / 2)
            .attr("x2", function (d, i) {
                return cfg.w / 2 * (1 - cfg.factor * Math.sin(rotateAngle + i * cfg.radians / total));
            })
            .attr("y2", function (d, i) {
                return cfg.h / 2 * (1 - cfg.factor * Math.cos(rotateAngle + i * cfg.radians / total));
            })
            .attr("class", "line")
            .style("stroke", "grey")
            .style("stroke-width", "1px");

        axis.append("text")
            .attr("class", "legend")
            .text(function (d) {
                return d
            })
            .style("font-family", "sans-serif")
            .style("font-size", "11px")
            .attr("text-anchor", "middle")
            .attr("dy", "1.5em")
            .attr("transform", function (d, i) {
                return "translate(0, -10)"
            })
            .attr("x", function (d, i) {
                return cfg.w / 2 * (1 - cfg.factorLegend * Math.sin(rotateAngle + i * cfg.radians / total)) - 60 * Math.sin(rotateAngle + i * cfg.radians / total);
            })
            .attr("y", function (d, i) {
                return cfg.h / 2 * (1 - Math.cos(rotateAngle + i * cfg.radians / total)) - 20 * Math.cos(rotateAngle + i * cfg.radians / total);
            })
            .on('click', function (d, i) {
                // console.log("mouse click on label");
                var distribution = g.append("g")
                    .attr("class","distribution")
                    .attr("transform", "translate(" + (cfg.w / 2 ) + ", " + (cfg.h / 2) + ")");

                for(var k=1;k < cfg.levels; k++){
                    var factor = cfg.factor * radius/ cfg.levels;
                    var x1 = (k-1)*factor*(- Math.sin(rotateAngle + i * cfg.radians / total));
                    var y1 = (k-1)*factor*(- Math.cos(rotateAngle + i * cfg.radians / total));
                    var x2 = k*factor*(- Math.sin(rotateAngle + i * cfg.radians / total));
                    var y2 =  k*factor*(- Math.cos(rotateAngle + i * cfg.radians / total));
                    var colorId = axisDistribution[i][k];

                    distribution.append("svg:line")
                        .attr("x1", x1)
                        .attr("y1", y1)
                        .attr("x2", x2)
                        .attr("y2", y2)
                        .style("stroke", cfg.densityColors[colorId])
                        .style("stroke-opacity", ".8")
                        .style("stroke-width", "10px");
                }
            })
            .on('mouseout', function (d, i) {
                    // console.log("mouse out!!!");
                var distr =  g.selectAll(".distribution");
                distr.remove();
                });

        d.forEach(function (y, x) {
            dataValues = [];
            g.selectAll(".nodes")
                .data(y, function (j, i) {
                    dataValues.push([
                        cfg.w / 2 * (1 - (parseFloat(Math.max(j.value, 0)) / cfg.maxValue) * cfg.factor * Math.sin(rotateAngle + i * cfg.radians / total)),
                        cfg.h / 2 * (1 - (parseFloat(Math.max(j.value, 0)) / cfg.maxValue) * cfg.factor * Math.cos(rotateAngle + i * cfg.radians / total))
                    ]);
                });
            dataValues.push(dataValues[0]);
            g.selectAll(".area")
                .data([dataValues])
                .enter()
                .append("polygon")
                .attr("class", "radar-chart-serie" + series)
                .style("stroke-width", "2px")
                .style("stroke", cfg.color(series))
                .attr("points", function (d) {
                    var str = "";
                    for (var pti = 0; pti < d.length; pti++) {
                        str = str + d[pti][0] + "," + d[pti][1] + " ";
                    }
                    return str;
                })
                .style("fill", function (j, i) {
                    return cfg.color(series)
                })
                .style("fill-opacity", cfg.opacityArea)
                .on('mouseover', function (d) {
                    z = "polygon." + d3.select(this).attr("class");
                    g.selectAll("polygon")
                        .transition(200)
                        .style("fill-opacity", 0.1);
                    g.selectAll(z)
                        .transition(200)
                        .style("fill-opacity", .7);

                })
                .on('mouseout', function () {
                    g.selectAll("polygon")
                        .transition(200)
                        .style("fill-opacity", cfg.opacityArea);
                });
            series++;
        });
        series = 0;

        d.forEach(function (y, x) {
            g.selectAll(".nodes")
                .data(y).enter()
                .append("svg:circle")
                .attr("class", "radar-chart-serie" + series)
                .attr('r', cfg.radius)
                .attr("alt", function (j) {
                    return Math.max(j.value, 0)
                })
                .attr("cx", function (j, i) {
                    return cfg.w / 2 * (1 - (Math.max(j.value, 0) / cfg.maxValue) * cfg.factor * Math.sin(rotateAngle + i * cfg.radians / total));
                })
                .attr("cy", function (j, i) {
                    return cfg.h / 2 * (1 - (Math.max(j.value, 0) / cfg.maxValue) * cfg.factor * Math.cos(rotateAngle + i * cfg.radians / total));
                })
                .attr("data-id", function (j) {
                    return j.axis
                })
                .style("fill", cfg.color(series)).style("fill-opacity", .9)
                .on('mouseover', function (d) {
                    newX = parseFloat(d3.select(this).attr('cx')) - 10;
                    newY = parseFloat(d3.select(this).attr('cy')) - 5;

                    tooltip
                        .attr('x', newX)
                        .attr('y', newY)
                        .text(Format(d.value))
                        .transition(200)
                        .style('opacity', 1);

                    z = "polygon." + d3.select(this).attr("class");
                    g.selectAll("polygon")
                        .transition(200)
                        .style("fill-opacity", 0.1);
                    g.selectAll(z)
                        .transition(200)
                        .style("fill-opacity", .7);
                })
                .on('mouseout', function () {
                    tooltip
                        .transition(200)
                        .style('opacity', 0);
                    g.selectAll("polygon")
                        .transition(200)
                        .style("fill-opacity", cfg.opacityArea);
                })
                .append("svg:title")
                .text(function (j) {
                    return Math.max(j.value, 0)
                });

            series++;
        });
        //Tooltip
        tooltip = g.append('text')
            .style('opacity', 0)
            .style('font-family', 'sans-serif')
            .style('font-size', '13px');
    }
    
    
};